home *** CD-ROM | disk | FTP | other *** search
- /* The EtermView implementation.
-
- For legal stuff see the file COPYRIGHT. */
-
- #import <dpsclient/dpsclient.h>
- #import <mach/mach.h>
- #import <libc.h>
- #import <stdio.h>
- #import <stdlib.h>
- #import <sys/ioctl.h>
- #import <sys/param.h>
- #import <sys/time.h>
-
- #import "EditListener.h"
- #import "EtermView.h"
- #import "EmacsApp.h"
- #import "etermSupport.h"
- #import "defaults.h"
- #import "display.h"
-
- extern char **environ;
-
- /* These are the window size limits imposed by GNUEmacs. */
- #define MINWIDTH 10
- #define MINHEIGHT 5
- #define MAXWIDTH 300
- #define MAXHEIGHT 300
-
- /* Function prototypes for display.pswm */
- void *new_display_rock (EtermView *theView);
- void input_from_emacs (int fd, void *theDisplay);
-
- /* Function prototypes for keycode.c */
- void kc_init (void);
- int kc_keyforcode (int code, int flags);
-
- /* write(2), except it will keep retrying upon partial success. */
- static int
- write_safely (int fd, char *buf, int n)
- {
- int i, start = 0;
-
- while (start < n)
- {
- i = write (fd, buf + start, n - start);
- if (i == -1)
- return i; /* Some error */
- start += i;
- }
- return n;
- }
-
- /* Handle a connection to the event server socket */
- static void
- connection_from_emacs (int fd, void *rock)
- {
- EtermView *view = (EtermView *) rock;
- int newfd = accept_server_connection (fd);
-
- if (newfd == -1)
- return;
-
- if ([view eventChannel])
- close (newfd);
- else
- [view setEventChannel: fdopen (newfd, "w")];
- }
-
- @implementation EtermView
-
- + initialize
- {
- static NXDefaultsVector etermDefaults =
- {
- {"NXAutoLaunch", "NO" },
- {"NXFixedPitchFontSpacing", "0.95" },
- {"HideOnAutoLaunch", "NO" },
- {"EmacsPath", DEFAULT_EMACS_PATH},
- {"LispPath", DEFAULT_LISP_PATH},
- {NULL},
- };
- const char *sTypes[2], *rTypes[2];
-
- sTypes[0] = NXAsciiPboardType;
- sTypes[1] = NULL;
- rTypes[0] = NXAsciiPboardType;
- rTypes[1] = NULL;
-
- NXRegisterDefaults ([NXApp appName], etermDefaults);
- [NXApp registerServicesMenuSendTypes: sTypes andReturnTypes: rTypes];
- kc_init ();
-
- return self;
- } /* +initialize */
-
- -initFrame: (const NXRect *) newFrame
- {
- self = [super initFrame: newFrame];
- [self setFlipped: YES];
- #if 0
- [self notifyAncestorWhenFrameChanged: YES];
- #endif
-
- spacing = atof (NXGetDefaultValue ([NXApp appName],
- "NXFixedPitchFontSpacing"));
- /* Check for sane values of spacing. */
- if (spacing < 0.9)
- spacing = 0.9;
- else if (spacing > 2.0)
- spacing = 2.0;
- [self setFont: [self font]];
- [[NXApp fontManager] setSelFont: [self font] isMultiple: NO];
- return self;
- } /* -initFrame: */
-
- -(float) spacing
- {
- return spacing;
- }
-
- -setSpacing: (float) newSpacing
- {
- char val[20];
-
- spacing = newSpacing;
- [self setFont: [self font]];
- sprintf (val, "%f", newSpacing);
- NXWriteDefault ([NXApp appName], "NXFixedPitchFontSpacing", val);
- return self;
- }
-
- -font
- {
- return [Font userFixedPitchFontOfSize: (float) 0 matrix: NX_FLIPPEDMATRIX];
- } /* -font */
-
- -setFont: newFont
- {
- NXCoord ascender, descender, lineHeight;
- NXRect frameRect, contentRect;
- Font *screenfont;
- int leading;
-
- /* NXTextFontInfo is broken for screen fonts, so call it before converting
- the font to a screenfont. */
- NXTextFontInfo (newFont , &ascender, &descender, &lineHeight);
- screenfont = [newFont screenFont];
- if (screenfont)
- newFont = screenfont;
-
- leading = (spacing - 1.0) * lineHeight;
- fontHeight = (int) (lineHeight * spacing + leading);
- fontWidth = (float) ([newFont getWidthOf : " "]
- - [newFont getWidthOf : " "] + 0.5);
- fontDescender = (int) (descender + leading);
-
- [newFont set];
- if (screenfont)
- set_font ();
- else
- fix_font (fontWidth);
- displayFont = newFont;
-
- /* Snap the window size to a 1 x 1 character grid. */
- [window getFrame: &frameRect];
- [self windowWillResize: self toSize: &frameRect.size];
- [Window getContentRect: &contentRect forFrameRect: &frameRect
- style: [window style]];
- [window sizeWindow: contentRect.size.width : contentRect.size.height];
- [self windowDidResize: self];
- [self display];
-
- return self;
- } /* -setFont: */
-
- /* Sent by fontManager. */
- -changeFont: sender
- {
- id selectedFont;
-
- /* Get the font selected in the FontPanel. */
- selectedFont = [[NXApp fontManager]
- convertFont: [[NXApp fontManager] selFont]];
- [self setFont: selectedFont];
- [Font setUserFixedPitchFont: selectedFont];
- return self;
- } /* -changeFont: */
-
- -(FILE *) eventChannel;
- {
- return eventChannel;
- } /* -eventChannel */
-
- -setEventChannel: (FILE *) fp;
- {
- eventChannel = fp;
- return self;
- } /* -setEventChannel: */
-
- /* Constrain window so that the content view has an integral width in terms
- of characters. XXX this method needs some cleaning up to stop the window
- from flashing while resizing. */
- -windowWillResize: sender toSize: (NXSize *) frameSize;
- {
- static int oldw = 0, oldh = 0;
- int neww, newh;
- NXRect frameRect, contentRect;
- int newwidth, newheight;
- int style = [window style];
-
- NXSetRect (&frameRect, 0.0, 0.0, frameSize->width, frameSize->height);
- [Window getContentRect: &contentRect forFrameRect: &frameRect style: style];
-
- newwidth = (int) (contentRect.size.width + fontWidth / 2 - BORDER_WIDTH * 2);
- newheight = (int) (contentRect.size.height
- + fontHeight / 2 - BORDER_WIDTH * 2);
-
- newwidth -= newwidth % fontWidth;
- newheight -= newheight % fontHeight;
-
- if (newwidth < MINWIDTH * fontWidth)
- newwidth = MINWIDTH * fontWidth;
- if (newwidth > MAXWIDTH * fontWidth)
- newwidth = MAXWIDTH * fontWidth;
-
- if (newheight < MINHEIGHT * fontHeight)
- newheight = MINHEIGHT * fontHeight;
- if (newheight > MAXHEIGHT * fontHeight)
- newheight = MAXHEIGHT * fontHeight;
-
- contentRect.size.width = (NXCoord) newwidth + BORDER_WIDTH * 2;
- contentRect.size.height = (NXCoord) newheight + BORDER_WIDTH * 2;
- [Window getFrameRect:&frameRect forContentRect:&contentRect style:style];
-
- frameSize->width = frameRect.size.width;
- frameSize->height = frameRect.size.height;
-
- newh = newheight / fontHeight;
- neww = newwidth / fontWidth;
- if (newh != oldh || neww != oldw)
- {
- [self showTitle: newh : neww];
- oldh = newh;
- oldw = neww;
- }
- return self;
- } /* -windowWillResize:toSize: */
-
- /* Convert size to number of characters in content view. Inform child emacs
- process of our new size. */
- -windowDidResize: sender
- {
- NXRect frameRect, contentRect;
- int style = [window style];
- struct winsize winsize;
-
- [window getFrame: &frameRect];
- [Window getContentRect: &contentRect forFrameRect: &frameRect style: style];
-
- lines = (int) ((contentRect.size.height - BORDER_WIDTH * 2) / fontHeight);
- cols = (int) ((contentRect.size.width - BORDER_WIDTH * 2) / fontWidth);
- [self showTitle: lines : cols];
-
- /* emacs doesn't do anything with a TIOCCSWINSZ if LINES nor COLS change,
- so send a redraw screen in that case. */
- winsize.ws_row = lines;
- winsize.ws_col = cols;
- winsize.ws_xpixel = (int) contentRect.size.width;
- winsize.ws_ypixel = (int) contentRect.size.height;
- ioctl (masterChannel, TIOCSWINSZ, &winsize);
- if (eventChannel)
- fprintf (eventChannel, "(redraw-display)\n");
- return self;
- } /* -windowDidResize: */
-
- /* Start up the child emacs process, perhaps on a file. */
- -startEmacs
- {
- int master, slave, ptynumber, portno, i, n;
- char **args, **env;
- char *path;
- const char *lisp;
-
- /* Grab a pty/tty pair */
- create_channel (&master, &slave, &ptynumber);
- masterChannel = master;
-
- /* Create the server socket */
- eventServerSocket = create_server_socket (&portno);
- DPSAddFD (eventServerSocket, connection_from_emacs,
- (void *) self, NX_RUNMODALTHRESHOLD);
-
- /* Frob the environment */
- env = patch_env (environ, portno);
-
- /* Make sure the size is set correctly */
- [self windowDidResize: self];
-
- args = calloc (startNum + 6, sizeof (char *));
- args[0] = "emacs";
-
- path = malloc (MAXPATHLEN + 1);
- lisp = NXGetDefaultValue ([NXApp appName], "LispPath");
- args[1] = "-l";
- args[3] = "-f";
- args[4] = "start-event-server";
- n = 5;
- if (strrchr (lisp, '/'))
- args[2] = (char *)lisp;
- else
- {
- if ([[NXBundle mainBundle] getPath: path forResource: lisp ofType: NULL])
- args[2] = path;
- else
- n = 1;
- }
-
- for (i=0 ; i<startNum ; i++) {
- args[n++] = startFiles[i];
- }
-
- /* Fork off the Emacs */
- fork_shell ((char *)NXGetDefaultValue ([NXApp appName], "EmacsPath"),
- args, env, slave);
- free (path);
- free (args);
- close (slave);
-
- rock = new_display_rock(self);
- DPSAddFD (master, input_from_emacs, rock, NX_RUNMODALTHRESHOLD);
- [window display];
- return self;
- } /* -startEmacs: */
-
- -(BOOL) acceptsFirstResponder
- {
- return YES;
- } /* -acceptsFirstResponder */
-
- /* Keyboard input is given to the child emacs process. XXX this method needs some cleeaning up. */
- -keyDown: (NXEvent *) theEvent;
- {
- NXEvent eventbuf;
- char buf[1024];
- int i = 0;
- int code;
-
- if (theEvent->flags & NX_NUMERICPADMASK
- && theEvent->data.key.charCode >= 0xac
- && theEvent->data.key.charCode <= 0xaf)
- {
- /* Arrow keys (left, up, right, down) */
- if (theEvent->flags & NX_SHIFTMASK)
- buf[i++] = "\302\326\306\026"[theEvent->data.key.charCode - 0xac];
- else if (theEvent->flags & NX_CONTROLMASK)
- buf[i++] = "\001\274\005\276"[theEvent->data.key.charCode - 0xac];
- else if (theEvent->flags & NX_ALTERNATEMASK)
- buf[i++] = "\202\220\206\216"[theEvent->data.key.charCode - 0xac];
- else
- buf[i++] = "\002\020\006\016"[theEvent->data.key.charCode - 0xac];
- }
- else if (theEvent->flags & NX_NUMERICPADMASK
- && theEvent->data.key.charCode == 0x03)
- {
- /* Enter key */
- buf[i++] = '\r';
- }
- else if (theEvent->flags & NX_ALTERNATEMASK)
- {
- /* Handle ALT key as a META key */
- code = kc_keyforcode(theEvent->data.key.keyCode, theEvent->flags);
- if (code != -1) {
- buf[i++] = code | 0x80;
- }
- }
- else buf[i++] = theEvent->data.key.charCode;
-
- /* Grab as many keypressed events as we can from a modal event loop */
- while (i < sizeof (buf)
- && (theEvent = [NXApp peekNextEvent: NX_ALLEVENTS into: &eventbuf])
- && theEvent->type == NX_KEYDOWN
- && !(theEvent->flags & NX_COMMANDMASK))
- {
- theEvent = [NXApp getNextEvent: NX_ALLEVENTS];
-
- if (theEvent->flags & NX_NUMERICPADMASK
- && theEvent->data.key.charCode >= 0xac
- && theEvent->data.key.charCode <= 0xaf)
- {
- /* Arrow keys (left, up, right, down) */
- if (theEvent->flags & NX_SHIFTMASK)
- buf[i++] = "\302\326\306\026"[theEvent->data.key.charCode - 0xac];
- else if (theEvent->flags & NX_CONTROLMASK)
- buf[i++] = "\001\274\005\276"[theEvent->data.key.charCode - 0xac];
- else if (theEvent->flags & NX_ALTERNATEMASK)
- buf[i++] = "\202\220\206\216"[theEvent->data.key.charCode - 0xac];
- else
- buf[i++] = "\002\020\006\016"[theEvent->data.key.charCode - 0xac];
- }
- else if (theEvent->flags & NX_NUMERICPADMASK
- && theEvent->data.key.charCode == 0x03)
- {
- /* Enter key */
- buf[i++] = '\r';
- }
- else if (theEvent->flags & NX_ALTERNATEMASK)
- {
- /* Handle ALT key as a META key */
- code = kc_keyforcode (theEvent->data.key.keyCode, theEvent->flags);
- if (code != -1)
- buf[i++] = code | 0x80;
- }
- else buf[i++] = theEvent->data.key.charCode;
- }
-
- write_safely (masterChannel, buf, i);
- obscure_cursor ();
-
- return self;
- } /* -keyDown: */
-
- /* Mouse input is converted to a character position and given to the child
- emacs process, but only if the emacs has opened an event port. */
- -mouseEvent: (NXEvent *) theEvent : (int) button;
- {
- int x, y;
- char buf[35];
-
- if (!eventChannel)
- return self;
-
- [self convertPoint: &theEvent->location fromView:nil];
- x = (int) ((theEvent->location.x - BORDER_WIDTH) / fontWidth);
- y = (int) ((theEvent->location.y - BORDER_WIDTH) / fontHeight);
-
- if (x < 0)
- x = 0;
- if (y < 0)
- y = 0;
- if (x >= cols)
- x = cols - 1;
- if (y >= lines)
- y = lines - 1;
-
- if (oldx != x || oldy != y) {
-
- sprintf (buf, "\030%c(%d %d %d 1)\r", 0,
- (button + ((theEvent->flags & NX_SHIFTMASK) ? 8 : 0)
- + ((theEvent->flags & NX_CONTROLMASK) ? 16 : 0)
- + ((theEvent->flags & NX_ALTERNATEMASK) ? 32 : 0)), x, y);
- write_safely (masterChannel, buf, 2+strlen (buf+2));
-
- oldx = x;
- oldy = y;
- }
-
- return self;
- } /* -mouseEvent:: */
-
-
- -mouseDown: (NXEvent *) theEvent;
- {
- [self mouseEvent: theEvent: 1];
- oldmask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
- return self;
- } /* -mouseDown: */
-
- -mouseUp: (NXEvent *) theEvent;
- {
- oldmask = [window removeFromEventMask:NX_LMOUSEDRAGGEDMASK];
- [self mouseEvent: theEvent: 1 + 128];
- return self;
- } /* -mouseUp */
-
- -mouseDragged: (NXEvent *) theEvent;
- {
- NXEvent *foundEvent = theEvent, *searchEvent;
- int filterCount = 0;
-
- while ((++filterCount < 10) &&
- ((searchEvent = [NXApp getNextEvent:NX_LMOUSEDRAGGEDMASK waitFor:0.034
- threshold:NX_MODALRESPTHRESHOLD]) != NULL))
- foundEvent = searchEvent;
-
- [self mouseEvent: foundEvent: 1 + 128];
- return self;
- } /* -mouseDragged */
-
- -rightMouseDown: (NXEvent *) theEvent;
- {
- [self mouseEvent: theEvent: 4];
- return self;
- } /* rightMouseDown: */
-
- -rightMouseUp: (NXEvent *) theEvent;
- {
- [self mouseEvent: theEvent: 4 + 128];
- return self;
- } /* rightMouseUp: */
-
- -(BOOL) emacsOn
- {
- if (eventChannel) {
- if (startNum > 0) {
- int index;
-
- /* Now that we have a connection established, make sure all the open
- requests that have line numbers are pointed at the right place. */
- for (index = 0 ; index < startNum ; index++) {
- if (startLines[index] >= 0)
- [self openFile:startFiles[index] onHost:""
- atTrueLine:startLines[index]];
- else
- [self newFile:startFiles[index]];
- }
- startNum = 0;
- }
- return YES;
- }
- else
- return NO;
- } /* -emacsOn */
-
- -(BOOL) newFile: (const char *) path
- {
- if (!eventChannel)
- return [self addFile:path atLine:-1];
-
- fprintf (eventChannel, "(find-file \"%s\")\n", path);
- fflush (eventChannel);
- return YES;
- } /* -newFile: */
-
- /* Quit, cut, copy, paste, and undo messages are sent to the child's event
- port. */
- -quitEmacs
- {
- if (!eventChannel)
- return nil;
- fprintf (eventChannel, "(event-quit)\n");
- fflush (eventChannel);
- return self;
- } /* -quitEmacs */
-
- -pasteboard
- {
- if (!currentPasteboard)
- currentPasteboard = [self appPasteboard];
- return currentPasteboard;
- } /* -pasteboard */
-
- -appPasteboard
- {
- if (!mainPasteboard)
- mainPasteboard = [Pasteboard new];
- return mainPasteboard;
- } /* -appPasteboard */
-
- -setPasteboard: pboard
- {
- if (pboard != nil)
- currentPasteboard = pboard;
- return self;
- } /* -setPasteboard: */
-
- -(BOOL) sendEmacsEvent: (char *) theEvent
- {
- if (!eventChannel)
- return NO;
- fprintf (eventChannel, "%s\n", theEvent);
- fflush (eventChannel);
- return YES;
- } /* -(BOOL) sendEmacsEvent: */
-
- -pasteboardWritten
- {
- pasteboardWaiting = NO;
- return self;
- }
-
- -(BOOL)pasteboardWaiting
- {
- return pasteboardWaiting;
- }
-
-
- -undo: sender;
- {
- [self sendEmacsEvent: "(undo)"];
- return self;
- } /* -undo: */
-
- -save: sender;
- {
- [self sendEmacsEvent: "(save-buffer)"];
- return self;
- } /* -save: */
-
- -saveAll: sender;
- {
- [self sendEmacsEvent: "(save-some-buffers t)"];
- return self;
- } /* -saveAll: */
-
- -cut: sender;
- {
- [self cutTo: [self appPasteboard]];
- return self;
- } /* -cut: */
-
- -copy: sender;
- {
- [self copyTo: [self appPasteboard]];
- return self;
- } /* -copy: */
-
- -paste: sender;
- {
- [self pasteFrom: [self appPasteboard]];
- return self;
- } /* -paste: */
-
- -open: sender;
- {
- int i;
- char *path;
- const char *directory;
- const char *const *fileNames;
-
- if (!eventChannel)
- return self;
- if (!openPanel)
- openPanel = [OpenPanel new];
- [openPanel allowMultipleFiles: YES];
- [openPanel chooseDirectories: NO];
- if ([openPanel runModal])
- {
- directory = [openPanel directory];
- fileNames = [openPanel filenames];
- if (fileNames)
- {
- for (i = 0; fileNames[i]; i++)
- {
- path = malloc (2 + strlen (directory) + strlen (fileNames[i]));
- strcat (strcat (strcpy (path, directory), "/"), fileNames[i]);
- fprintf (eventChannel, "(find-file \"%s\")\n", path);
- fflush (eventChannel);
- free (path);
- }
- }
- }
- return self;
- } /* -open: */
-
- -saveAs: sender;
- {
- const char *path;
-
- if (!eventChannel)
- return self;
- if (!savePanel)
- savePanel = [SavePanel new];
- if ([savePanel runModal])
- {
- path = [savePanel filename];
- if (path)
- {
- fprintf (eventChannel, "(write-file \"%s\")\n", path);
- fflush (eventChannel);
- }
- }
- return self;
- } /* -saveAs: */
-
- -(BOOL) cutTo: pasteboard
- {
- return [[self setPasteboard: pasteboard] sendEmacsEvent: "(event-cut)"];
- } /* -(BOOL) cutTo: */
-
- -(BOOL) copyTo: pasteboard
- {
- return [[self setPasteboard: pasteboard] sendEmacsEvent: "(event-copy)"];
- } /* -(BOOL) copyTo: */
-
- -(BOOL) pasteFrom: pasteboard
- {
- const NXAtom *types, *p;
- char *data;
- int len;
-
- if (!eventChannel || !pasteboard)
- return NO;
- types = [pasteboard types];
- for (p = types; *p && strcmp (*p, NXAsciiPboardType); p++);
-
- if (*p && [pasteboard readType: NXAsciiPboardType data: &data length: &len]
- && len)
- {
- int c;
- char *tosend = data;
-
- fputs("(event-paste \"", eventChannel);
-
- /* Write out string, quoting quote, backslash, and newline */
- for (tosend = data; len--; tosend++)
- {
- switch (c = *tosend)
- {
- case '\n':
- fputs ("\\n", eventChannel);
- break;
- case '\\':
- case '\"':
- putc('\\', eventChannel);
- /* FALL THROUGH */
- default:
- putc (c, eventChannel);
- break;
- }
- }
- fputs ("\")\n", eventChannel);
- fflush (eventChannel);
- vm_deallocate (task_self (), (vm_address_t) data, len);
- }
- return YES;
- } /* -(BOOL) pasteFrom: */
-
- -getDimensions: (int *) linesPtr : (int *) colsPtr
- {
- *linesPtr = lines;
- *colsPtr = cols;
- return self;
- } /* -getDimensions:: */
-
- -(Font *) getDisplayFont:
- (int *) heightPtr :
- (int *) widthPtr :
- (int *) descenderPtr
- {
- *heightPtr = fontHeight;
- *widthPtr = fontWidth;
- *descenderPtr = fontDescender;
- return displayFont;
- } /* -getDisplayFont::: */
-
- -showTitle: (int) newLines : (int) newColumns
- {
- char *newtitle;
-
- if (!titleprefix)
- return self;
- newtitle = malloc (22 + strlen (titleprefix));
- sprintf (newtitle, "%s (%dx%d)", titleprefix, newColumns, newLines);
- [(Window *) window setTitle: newtitle];
- free (newtitle);
- return self;
- } /* -showTitle:: */
-
- -setTitle: (char *) title
- {
- titleprefix = title;
- [self showTitle: lines : cols];
- return self;
- } /* -setTitle: */
-
- -validRequestorForSendType: (NXAtom) typeSent
- andReturnType: (NXAtom) typeReturned
- {
- /* Check to make sure that the types are ones that we can handle. */
- if (eventChannel && (typeSent == NXAsciiPboardType || typeSent == NULL)
- && (typeReturned == NXAsciiPboardType || typeReturned == NULL))
- return self;
- /* Otherwise, return the default. */
- return [super validRequestorForSendType: typeSent
- andReturnType: typeReturned];
- } /* -validRequestorForSendType:andReturnType: */
-
- -(BOOL) writeSelectionToPasteboard: pboard types: (NXAtom *) types
- {
- const NXAtom *p;
- BOOL rightType = NO;
-
- if (eventChannel && pboard && rock)
- {
- p = types;
- while (*p) {
- if (!strcmp(*p, NXAsciiPboardType)) {
- rightType = YES;
- break;
- }
- p++;
- }
-
- /* Ok, so this is slightly sick. We loop until emacs receives and
- processes the event. Then we know we've completely dealt with the
- pasteboard. We can't return until something has been pasted to it.
- Or the application will probably end up choking. We put in a
- timeout to prevent hanging. */
- if (rightType) {
- struct timeval theTime;
- struct timezone dummy;
- long curTime, elapsedTime;
-
- gettimeofday(&theTime, &dummy);
- curTime = theTime.tv_sec + theTime.tv_usec / 1000000;
- elapsedTime = 0;
- pasteboardWaiting = YES;
- if (![self copyTo: pboard])
- return NO;
- while (pasteboardWaiting &&
- (elapsedTime < 5)) {
- input_from_emacs(masterChannel, rock);
- gettimeofday(&theTime, &dummy);
- elapsedTime = (theTime.tv_sec + theTime.tv_usec / 1000000) - curTime;
- }
- if (pasteboardWaiting) {
- NXBeep();
- NXBeep();
- return NO;
- }
- return YES;
- }
- }
- return NO;
- } /* -writeSelectionToPasteboard:types: */
-
- -readSelectionFromPasteboard: pboard
- {
- [self sendEmacsEvent: "(call-interactively 'kill-region)"];
- [self pasteFrom: pboard];
- return self;
- } /* -readSelectionFromPasteboard: */
-
-
- /* Opening up a file remotely and showing the right line number. */
- -(int)openFile : (char *) fileName
- onHost : (char *) hostName
- atTrueLine : (int) line
- {
- if (!eventChannel)
- return [self addFile:fileName atLine:line];
-
- fprintf(eventChannel, "(find-file \"%s\")\n", fileName);
- fprintf(eventChannel, "(goto-line %d)\n", line);
- fprintf(eventChannel, "(if (not overlay-arrow-position)");
- fprintf(eventChannel, " (progn (setq overlay-arrow-position (point-marker)) ");
- fprintf(eventChannel, " (setq overlay-arrow-string \"=>\")))\n");
- fprintf(eventChannel, "(set-marker overlay-arrow-position ");
- fprintf(eventChannel, " (- (point) (current-column)))\n");
- fflush(eventChannel);
- return YES;
- }
-
- -(int)openFile : (char *) fileName
- onHost : (char *) hostName
- fromTrueLine : (int) line1
- to : (int) line2
- {
- return [self openFile:fileName onHost:hostName atTrueLine:line1];
- }
-
- - (BOOL)addFile:(const char *)path atLine:(int)line
- {
- if (startFiles == NULL) {
- startFiles = (char **)malloc((startNum + 1) * sizeof(char *));
- startLines = (int *)malloc((startNum + 1) * sizeof(int));
- }
- else {
- startFiles = (char **)realloc(startFiles, (startNum+1) * sizeof (char *));
- startLines = (int *)realloc(startLines, (startNum+1) * sizeof (int));
- }
- if ((startFiles == NULL) || (startLines == NULL)) return NO;
-
- startLines[startNum] = line;
- startFiles[startNum] = strcpy (malloc (1 + strlen (path)), path);
- startNum++;
- return YES;
- }
-
- @end
-